package smartt.styy.auth.controller;

import lombok.extern.slf4j.Slf4j;
import smartt.styy.auth.constants.RedisConstants;
import smartt.styy.auth.constants.ServerConstants;
import smartt.styy.auth.model.request.JwtAuthenticationRequest;
import smartt.styy.auth.model.request.VerifyTokenReq;
import smartt.styy.auth.model.response.JwtUserInfoRsp;
import smartt.styy.auth.service.AuthService;
import smartt.styy.auth.util.RedisCacheUtil;
import smartt.styy.common.constant.RestCodeConstants;
import smartt.styy.common.constant.UserConstant;
import smartt.styy.common.exception.BaseException;
import smartt.styy.common.msg.ObjectRestResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping("jwt")
@Slf4j
@Api(value="AuthController",tags="[统一登录认证中心token相关]")
public class AuthController {
    
	@Value("${jwt.token-header}")
    private String tokenHeader;

    @Autowired
    private AuthService authService;

    @Autowired
	private RedisCacheUtil redisCacheUtil;
    
    /**
	 * Description:用户登录返回token <br>
	 * @author stf<br>
	 * @param JwtAuthenticationRequest <br>
	 * @return String <br>
	 * @throws BaseException <br>
	 * */
	@RequestMapping(value = "token", method = RequestMethod.POST)
    @ApiOperation(value="[用户登录返回token]-[用户登录post提交]", notes="用户登录返回token值")
    @ApiImplicitParam(name = "authenticationRequest", value = "用户注册authenticationRequest",
    	required = true, dataType = "JwtAuthenticationRequest")
    public ObjectRestResponse<Object> createAuthenticationToken(
            @RequestBody JwtAuthenticationRequest authenticationRequest) throws Exception {
        log.info(authenticationRequest.getUsername()+" require logging...");
        ObjectRestResponse<Object> objectRestResp = new ObjectRestResponse<Object>();
        Map<String,Object> restMap = new HashMap<String,Object>();
        
        //参数校验
        String username = authenticationRequest.getUsername();
        String password = authenticationRequest.getPassword();
        Integer userType = authenticationRequest.getUserType();
        if (StringUtils.isAnyBlank(username, password) || userType == null) {
        	log.error("[用户注册]-[手机号码注册]--参数为空！");
			objectRestResp.setStatus(UserConstant.USER_PHONE_REGISTER_CODE);
			objectRestResp.setMessage(UserConstant.USER_PHONE_REGISTER_MSG);
			objectRestResp.setRel(false);
			return objectRestResp;
        }
        
        String errNum =new String("");
		int errNums = 0;
		try {
			Object redisAccountErrNum =redisCacheUtil.getCache(
					RedisConstants.REDIS_ACCOUNT_PREFIX+RedisConstants.KEY_SPLIT+username);
			if(null != redisAccountErrNum){
				errNum = redisAccountErrNum.toString();
			}
			if(errNum !=null && !errNum.equals("")){
				errNums = Integer.parseInt(errNum);
			}
			if(errNums>5){
				//登录错误次数大于5次，今天不允许登录了
				objectRestResp.setStatus(UserConstant.USER_60100);
				objectRestResp.setMessage(UserConstant.USER_60100_MSG);
				objectRestResp.setRel(false);
				return objectRestResp;
			}
		} catch (Exception e) {
			log.error("[用户注册]-[手机号+密码登录]--系统内部错误！");
			throw new BaseException("[用户注册]-[手机号+密码登录]--系统内部错误，错误message:"+e.getMessage(),
					RestCodeConstants.SYSTEM_ERROR_CODE);
		}
        
        try {
        	restMap = authService.login(authenticationRequest);
        	
        	//登录成功重置错误次数
			redisCacheUtil.putCacheWithExpireTime(RedisConstants.REDIS_ACCOUNT_PREFIX+RedisConstants.KEY_SPLIT+username, 
					RedisConstants.REDIS_RIGHT_COUNT, RedisConstants.REDIS_VERIFTY_DEFALUT_EXPIRETIME);
        	
		} catch (Exception e) {
			log.error("[用户登录返回token]-[用户登录post提交]-异常，错误message:"+e.getMessage());
			
			errNums = errNums+1;
			try {
				redisCacheUtil.putCacheWithExpireTime(RedisConstants.REDIS_ACCOUNT_PREFIX+RedisConstants.KEY_SPLIT+username, 
						errNums, RedisConstants.REDIS_VERIFTY_DEFALUT_EXPIRETIME);
			} catch (Exception e1) {
				log.error("[用户注册]-[手机号+密码登录]--redis异常！");
				throw new BaseException("[用户注册]-[手机号+密码登录]--系统内部错误，错误message:"+e.getMessage(),
						RestCodeConstants.SYSTEM_ERROR_CODE);
			}
			
			throw new BaseException("[用户登录返回token]-[用户登录post提交]-异常，错误message:"+
					e.getMessage(),RestCodeConstants.THROW_ERROR_CODE);
		}
        
        
        objectRestResp.setStatus(RestCodeConstants.SUCCESS_CODE);
		objectRestResp.setData(restMap);
		objectRestResp.setRel(true);
		return objectRestResp;
    }
    
    /**
	 * Description:用户刷新token <br>
	 * @author stf<br>
	 * @param  <br>
	 * @return String <br>
	 * @throws BaseException <br>
	 * */
    @SuppressWarnings("unchecked")
	@RequestMapping(value = "refresh", method = RequestMethod.GET)
    @ApiOperation(value="[用户刷新token]", notes="用户刷新token，返回token值")
    public ObjectRestResponse<String> refreshAndGetAuthenticationToken(
            HttpServletRequest request) throws Exception {
        log.info("用户刷新token require logging ....");
        String refreshedToken = new String("");
        try {
    		String token = request.getHeader(tokenHeader);
    		refreshedToken = authService.refresh(token);
		} catch (Exception e) {
			log.error("[用户刷新token]-异常，错误message:"+e.getMessage());
			throw new BaseException("[用户刷新token]-异常，错误message:"+
					e.getMessage(),RestCodeConstants.THROW_ERROR_CODE);
		}
        log.info("[用户刷新token] end 。");
    	return new ObjectRestResponse<>().data(refreshedToken).rel(true);
    }

    
    /**
	 * Description:用户检验token <br>
	 * @author stf<br>
	 * @param  String<br>
	 * @return String <br>
	 * @throws BaseException <br>
	 * */
    @SuppressWarnings("unchecked")
	@PostMapping(value = "verify")
    @ApiOperation(value="[用户检验token]", notes="用户检验token，返回检验结果")
    @ApiImplicitParam(name = "param", value = "用户检验tokenparam", required = true, dataType = "VerifyTokenReq")
    public ObjectRestResponse<Object> verify(@RequestBody VerifyTokenReq param) throws Exception {
    	log.info("用户检验token require logging ....");
    	ObjectRestResponse<Object> objectRestResp = new ObjectRestResponse<Object>();
    	JwtUserInfoRsp jwtRsp = new JwtUserInfoRsp();
    	
    	String token = param.getToken();
    	String userId = param.getUserId();
    	Integer userType = param.getUserType();
    	
    	if (StringUtils.isAnyBlank(token)) {
			objectRestResp.setStatus(UserConstant.USER_PHONE_50810);
			objectRestResp.setMessage(UserConstant.USER_PHONE_50810_MSG);
			objectRestResp.setRel(false);
			return objectRestResp;
		}
    	
    	
    	if(userType ==null ){
    		log.warn("[认证中心]-[用户检验token]--userType传入错误！");
    		objectRestResp.setStatus(UserConstant.USER_PHONE_50810);
    		objectRestResp.setMessage(UserConstant.USER_PHONE_50810_MSG);
    		objectRestResp.setRel(false);
    		return objectRestResp;
    	}
    	boolean veritfyParams =true;
    	if(userType == ServerConstants.USER_TYPE_1 || userType == ServerConstants.USER_TYPE_4){
    		veritfyParams =false;
    	}
    	if(veritfyParams){
    		if (StringUtils.isAnyBlank(userId)) {
    			objectRestResp.setStatus(UserConstant.USER_PHONE_50810);
    			objectRestResp.setMessage(UserConstant.USER_PHONE_50810_MSG);
    			objectRestResp.setRel(false);
    			return objectRestResp;
    		}
    	}
    	
    	try {
    		jwtRsp =authService.validate(param);
    		
    		if(null == jwtRsp){
    			objectRestResp.setStatus(RestCodeConstants.TOKEN_ERROR_CODE);
    			objectRestResp.setMessage("token校验失败！");
    			objectRestResp.setRel(false);
    			return objectRestResp;
    		}
    		
		} catch (Exception e) {
			log.error("[用户检验token]-异常，错误message:"+e.getMessage());
			throw new BaseException("[用户检验token]-异常，错误message:"+
					e.getMessage(),RestCodeConstants.THROW_ERROR_CODE);
		}
    	log.info("[用户检验token] end 。");
        return new ObjectRestResponse<>().data(jwtRsp).rel(true);
    }
}
